package com.xes.hardwritingrecognition;

import android.content.Context;
import android.graphics.Bitmap;
import android.support.annotation.NonNull;

import com.alibaba.sdk.android.oss.ClientConfiguration;
import com.alibaba.sdk.android.oss.OSS;
import com.alibaba.sdk.android.oss.OSSClient;
import com.alibaba.sdk.android.oss.common.OSSConstants;
import com.alibaba.sdk.android.oss.common.auth.OSSFederationCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSFederationToken;
import com.alibaba.sdk.android.oss.common.utils.IOUtils;
import com.alibaba.sdk.android.oss.model.PutObjectRequest;

import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Locale;
import java.util.Random;

/**
 * Ali oss manager.
 *
 * @author wl
 * @since 2018/12/06 10:23
 */
final class OssManager {
    private static final String BUCKETNAME = "gpufiles";
    private static final String ENDPOINT = "oss-cn-beijing.aliyuncs.com";
    private static final String SERVER_INTERFACE = "http://ai-dw.speiyou.com:8081/oss-sts";
    private static OssManager mInstance;
    private boolean isEnabled = true;
    private final OSS mOss;

    public static OssManager getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new OssManager(context);
        }
        return mInstance;
    }

    private OssManager(Context context) {
        //该配置类如果不设置，会有默认配置，具体可看该类
        ClientConfiguration conf = new ClientConfiguration();
        conf.setConnectionTimeout(5 * 1000); // 连接超时，默认15秒
        conf.setSocketTimeout(5 * 1000); // socket超时，默认15秒
        conf.setMaxConcurrentRequest(5); // 最大并发请求数，默认5个
        conf.setMaxErrorRetry(1); // 失败后最大重试次数，默认2次

        final OSSFederationCredentialProvider credentialProvider = new OSSFederationCredentialProvider() {
            @Override
            public OSSFederationToken getFederationToken() {
                return getStsTokenAndOther();
            }
        };
        // we request manually to cache token and other info earlier
        // instead of caching when the first upload task called.
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    credentialProvider.getValidFederationToken();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        mOss = new OSSClient(context.getApplicationContext(), ENDPOINT, credentialProvider, conf);
    }

    private OSSFederationToken getStsTokenAndOther() {
        try {
            URL stsUrl = new URL(SERVER_INTERFACE);
            HttpURLConnection conn = (HttpURLConnection) stsUrl.openConnection();
            conn.setConnectTimeout(10000);
            InputStream input = conn.getInputStream();
            String jsonText = IOUtils.readStreamAsString(input, OSSConstants.DEFAULT_CHARSET_NAME);
            JSONObject jsonObj = new JSONObject(jsonText);
            // get oss enable info
            isEnabled = jsonObj.optBoolean("actionNeed");
            JSONObject ossObj = jsonObj.getJSONObject("credentials");
            String ak = ossObj.getString("accessKeyId");
            String sk = ossObj.getString("accessKeySecret");
            String token = ossObj.getString("securityToken");
            String expiration = ossObj.getString("expiration");
            return new OSSFederationToken(ak, sk, token, expiration);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public boolean isEnabled() {
        return isEnabled;
    }

    public void uploadAnImage(Bitmap bitmap, String value) {
        if (bitmap == null)
            return;
        if (!isEnabled())
            return;

        String filename = String.format(Locale.CHINESE, "%s_%d_%d_%s.png", value, System.currentTimeMillis(), new Random().nextInt(10000), "Android");
        // request
        PutObjectRequest put = new PutObjectRequest(BUCKETNAME, filename, bitmapToByteArray(bitmap));

        // async upload progress
        put.setProgressCallback(null);

        mOss.asyncPutObject(put, null);
    }

    private byte[] bitmapToByteArray(@NonNull Bitmap bitmap) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(bitmap.getByteCount());
        bitmap.compress(Bitmap.CompressFormat.PNG, 90, outputStream);
        return outputStream.toByteArray();
    }
}
